package org.lwjgl.demo.geometries;

import static org.lwjgl.opengl.ARBVertexArrayObject.glBindVertexArray;
import static org.lwjgl.opengl.GL11C.*;

/**
 * Cylinder圆柱体
 *
 * @author zhoudy
 * @date 2025/10/29 21:50
 */
public class Cylinder extends Mesh {
    private static final int SECTORS = 32;

    public Cylinder() {
        generateCylinder(0.3f, 1.0f); // 半径0.3，高度1.0
    }

    private void generateCylinder(float radius, float height) {
        java.util.ArrayList<Float> verticesList = new java.util.ArrayList<Float>();
        java.util.ArrayList<Integer> indicesList = new java.util.ArrayList<Integer>();

        float halfHeight = height / 2.0f;

        // ==================== 修改：生成圆柱体侧面 ====================
        for (int i = 0; i <= 1; ++i) {
            float y = -halfHeight + i * height;

            for (int j = 0; j <= SECTORS; ++j) {
                float sectorAngle = (float) (2 * Math.PI * j / SECTORS);
                float x = radius * (float) Math.cos(sectorAngle);
                float z = radius * (float) Math.sin(sectorAngle);

                // 位置
                verticesList.add(x);
                verticesList.add(y);
                verticesList.add(z);

                // 法线 (圆柱侧面的法线是水平向外的)
                verticesList.add((float) Math.cos(sectorAngle));
                verticesList.add(0.0f);
                verticesList.add((float) Math.sin(sectorAngle));

                // 纹理坐标
                float s = (float) j / SECTORS;
                float t = (float) i;
                verticesList.add(s);
                verticesList.add(t);
            }
        }

        // ==================== 修改：生成圆柱体索引 ====================
        for (int j = 0; j < SECTORS; ++j) {
            int k1 = j;
            int k2 = k1 + SECTORS + 1;

            indicesList.add(k1);
            indicesList.add(k2);
            indicesList.add(k1 + 1);

            indicesList.add(k1 + 1);
            indicesList.add(k2);
            indicesList.add(k2 + 1);
        }

        // ==================== 新增：生成圆柱体顶面和底面 ====================
        int baseIndex = verticesList.size() / 8;

        // 顶面
        for (int j = 0; j <= SECTORS; ++j) {
            float sectorAngle = (float) (2 * Math.PI * j / SECTORS);
            float x = radius * (float) Math.cos(sectorAngle);
            float z = radius * (float) Math.sin(sectorAngle);

            // 位置
            verticesList.add(x);
            verticesList.add(halfHeight);
            verticesList.add(z);

            // 法线 (向上)
            verticesList.add(0.0f);
            verticesList.add(1.0f);
            verticesList.add(0.0f);

            // 纹理坐标
            float s = (float) j / SECTORS;
            verticesList.add(s);
            verticesList.add(0.5f);
        }

        // 底面
        for (int j = 0; j <= SECTORS; ++j) {
            float sectorAngle = (float) (2 * Math.PI * j / SECTORS);
            float x = radius * (float) Math.cos(sectorAngle);
            float z = radius * (float) Math.sin(sectorAngle);

            // 位置
            verticesList.add(x);
            verticesList.add(-halfHeight);
            verticesList.add(z);

            // 法线 (向下)
            verticesList.add(0.0f);
            verticesList.add(-1.0f);
            verticesList.add(0.0f);

            // 纹理坐标
            float s = (float) j / SECTORS;
            verticesList.add(s);
            verticesList.add(0.5f);
        }

        // 顶面和底面索引
        for (int j = 0; j < SECTORS; ++j) {
            // 顶面三角形
            indicesList.add(baseIndex);
            indicesList.add(baseIndex + j + 1);
            indicesList.add(baseIndex + j + 2);

            // 底面三角形
            indicesList.add(baseIndex + SECTORS + 1);
            indicesList.add(baseIndex + SECTORS + 1 + j + 2);
            indicesList.add(baseIndex + SECTORS + 1 + j + 1);
        }

        // 转换为数组
        float[] vertices = new float[verticesList.size()];
        for (int i = 0; i < verticesList.size(); i++) {
            vertices[i] = verticesList.get(i);
        }

        int[] indices = new int[indicesList.size()];
        for (int i = 0; i < indicesList.size(); i++) {
            indices[i] = indicesList.get(i);
        }

        setupMesh(vertices, indices);
    }

    @Override
    public void render() {
        glBindVertexArray(vao);
        glDrawElements(GL_TRIANGLES, vertexCount, GL_UNSIGNED_INT, 0);
        glBindVertexArray(0);
    }
}
